#ifndef ADD_H
#define	ADD_H

#include "list.h"

template<typename Num1, typename Num2, int carry>
struct Add_
{
   typedef List<(Num1::data + Num2::data + carry) % 10,
           typename Add_<typename Num1::tail, typename Num2::tail,
           (Num1::data + Num2::data + carry) / 10>::result > result;
};

template<typename Num1, int carry>
struct Add_<Num1, EmptyList, carry>
{
   typedef List<(Num1::data + carry) % 10,
           typename Add_<typename Num1::tail, EmptyList,
           (Num1::data + carry) / 10>::result > result;
};

template<typename Num2, int carry>
struct Add_<EmptyList, Num2, carry>
{
   typedef List<(Num2::data + carry) % 10,
           typename Add_<EmptyList, typename Num2::tail,
           (Num2::data + carry) / 10>::result > result;
};

template<int carry>
struct Add_<EmptyList, EmptyList, carry>
{
   typedef List<carry % 10,
           typename Add_<EmptyList, EmptyList, carry / 10>::result > result;
};

template<>
struct Add_<EmptyList, EmptyList, 0>
{
   typedef EmptyList result;
};

template<typename Num1, typename Num2>
struct Add
{
   typedef typename Reverse<typename Add_<typename Reverse<Num1>::result,
           typename Reverse<Num2>::result, 0 >::result >::result result;
};

#endif

